Skip to content

[Feature] Etheos Websockets #87

Open
Caibran wants to merge 1 commit intoethanmoffat:masterfrom
Caibran:feature/websocket-support
Open

[Feature] Etheos Websockets #87
Caibran wants to merge 1 commit intoethanmoffat:masterfrom
Caibran:feature/websocket-support

Conversation

@Caibran
Copy link
Copy Markdown

@Caibran Caibran commented Mar 26, 2026

Adds a WebSocket to Etheos compadable with EOWeb

Uses IXWebSocket (v11.4.5) as the underlying library, pulled in automatically at cmake configure time when enabled.

The feature is completely opt-in: (as requested)

  • Build with: --websocket ON (or -DEOSERV_WANT_WEBSOCKET=ON)
  • Enable at runtime: WebSocketEnabled = yes in server.ini
  • Configure the port: WebSocketPort = 8082 (default)

When disabled (the default), there is zero impact on the existing build or runtime behavior.

Adds a WebSocket server that lets browser-based EO clients connect
directly to the game server without needing an external ws proxy.

Uses IXWebSocket (v11.4.5) as the underlying library, pulled in
automatically at cmake configure time when enabled.

The feature is completely opt-in:
- Build with: --websocket ON (or -DEOSERV_WANT_WEBSOCKET=ON)
- Enable at runtime: WebSocketEnabled = yes in server.ini
- Configure the port: WebSocketPort = 8082 (default)

When disabled (the default), there is zero impact on the existing
build or runtime behavior.
Comment thread src/eoserv_config.cpp
eoserv_config_default(config, "ThreadPoolThreads" , 0);
eoserv_config_default(config, "AutoCreateDatabase" , false);
eoserv_config_default(config, "WorldDumpFile" , "./world.bak.json");
eoserv_config_default(config, "WebSocketEnabled" , false);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this default enabled, I want web sockets to be a native feature not an optional addon

Comment thread src/eoserver.cpp

this->UpdateConfig();

#ifdef WEBSOCKET_SUPPORT
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the CMake arg and the #ifdef guards, this should be always enabled

Comment thread src/eoserver.cpp
}
}

void EOServer::OnClientRemoved(Client *client)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not seeing where this is called. What is this used for? Can BuryTheDead have a call into the wsserver that does something similar?

Comment thread src/eoserver.cpp
EOClient *client = static_cast<EOClient *>(rawclient);

if (client->Connected() && !client->Accepted() && client->start + delay < now)
if (client->Connected() && !client->Accepted() && !client->IsWebSocket() && client->start + delay < now)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hoping to have it so that all clients (both regular socket clients and web socket clients) could be in the same collection so that the implementation could handle stuff like this (i.e. client->IsWebSocket() check should not be necessary since the client method implementations can just handle this transparently). Is it possible to rearchitect the change around that design goal?

Comment thread src/socket.hpp
virtual ~Server();
virtual void OnClientRemoved(Client *) {}

virtual ~Server();
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix the indentation here

Comment thread src/wsclient.cpp
return false;
}

bool WSClient::Upload(FileType type, int id, InitReply init_reply)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be abstracted differently so there's no duplication between regular socket and web socket implementation? I'm guessing the only difference is in how the data is sent; the base class should call a virtual method that this class overrides with the websocket send logic.

Something like this

EOClient::Upload(args) {
/* base implementation that builds/encodes the packet */
this->SendFile(data);
}

EOClient::SendFile(const std::string& data) {
    // regular socket send
}

WSClient::SendFile(const std::string& data) {
    ws_send(combined);
}

Comment thread src/wsclient.cpp
return true;
}

void WSClient::Send(const PacketBuilder &builder)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, see if you can deduplicate the code using a similar method as described above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants